/*
 * DppmProcess.cpp
 *
 *  Created on: 31/01/2014
 *      Author: Bruno
 */

#include <stdlib.h>
#include "DppmBuffer.h"
#include "DppmParams.h"
#include <iostream>
#define DEBUG 1

using namespace std;


Tuple * optimalSolution(Tuple* &oldSol, Tuple * &newSol){

	if(oldSol != NULL){
	//	cout<<"optimalSolution(old,new): ( "<<oldSol->cost()<<" , " <<newSol->cost()<<" )"<<endl;
	}
	if ((oldSol != NULL)&&( oldSol->cost() <= newSol->cost() )){
		delete newSol;
		newSol = NULL;
		return oldSol;
	}
	delete oldSol;
	oldSol = NULL;
	return newSol;
}
//esta funcion aplica la poda
bool canBeOpt(DppmParams &dppmParms, Tuple * solOp , Tuple * T2){

	int timeMin = T2->times(T2->lastAct());
	int time = 0;
	int timeMode = 0;

	int costMin = T2->cost();
	int cost = 0;
	int costMode = 0;
	int * times = NULL;
	int * costs = NULL;

	for(int i = T2->lastAct(); i < dppmParms.getNumActivities(); i++){
		//obtengo el tiempo minimo posible para el resto de las activades sin asignar
		// y me fijo si se pasa del deadline
		for(int j = 0; j < dppmParms.getActivityNumModes(i); j++){
			times = dppmParms.getActivityModesTimes(i);
			costs = dppmParms.getActivityModesCosts(i);
			timeMode = times[j];
			costMode = costs[j];
			time = ((time == 0)||(time <= timeMode)) ? time : timeMode;
			cost = ((cost == 0)||(cost <= costMode)) ? cost : costMode;

		}
		timeMin += time;
		costMin += cost;
		if ((timeMin > dppmParms.getDeadline())||((solOp != NULL)&&(solOp->cost() <= costMin)))
			return false;

	}

	bool ret = ((solOp == NULL)||(solOp->cost() > costMin));
	if ( ret ){
	//	cout<<"Puede ser solucion!!"<<endl;
	}
	return ret;
}



void ProcessTuple(DppmParams &dppmParms, DppmBuffer &dppmBuff, Tuple * &solOpt){

	Tuple * T = dppmBuff.pop();

	if( T == NULL){
		#ifdef DEBUG
			cout<<"NO HAY MAS TUPLAS"<<endl;
		#endif
		return;
	}

	//int countActs = GetNumActivities(dppmParms);
	int numModes = dppmParms.getActivityNumModes(T->lastAct() + 1);
	Tuple * T2;
	for(int i = 0 ; i < numModes; i++){
		T2 = T->copy();
		T2->sigAct();
		T2->modes(T2->lastAct(),i);
		//calculo el tiempo y el costo que insume la nueva tupla
		//obtiene el tiempo maximo que demoran sus predecesores

		int time = dppmParms.getPredsMaxTime(T2);
		//obtengo el tiempo que insume la actividad T2->now en el modo i y se lo sumo
		int timeMode = (dppmParms.getActivityModesTimes(T2->lastAct()))[i];
		time += timeMode;
		//el tiempo de la tupla es el ma
		T2->times(T2->lastAct(),time);
		T2->time( (T2->time() <= time) ? time : T2->time() );

		//sumo el costo del modo de la nueva actividad

		T2->cost( T2->cost() + dppmParms.getActivityModesCosts(T2->lastAct())[i] );

		if( T2->isSolution() && T2->time() <= dppmParms.getDeadline()){
			solOpt = optimalSolution(solOpt,T2);
		}else{
			if((T2->times(T2->lastAct()) <= dppmParms.getDeadline()) && canBeOpt(dppmParms,solOpt,T2)){
				dppmBuff.push(T2);
			}else{
				delete T2;
			}
		}
	}//for
	delete T;


}




